﻿using System;
using System.Collections.Generic;
using System.Linq;
using TaskKernel.Domain.Interface;
using TaskKernel.Domain.Services.Role;

namespace TaskKernel.Domain.Services.Action
{
    public class DepartmentService : IDepartmentService
    {
        private readonly Dictionary<List<RoleEnum>, Func<IQueryable<Task>>> _dictPerm;
        private readonly IQueryTask _queryTask;
        private List<RoleEnum> _highPerm;
        private List<RoleEnum> _lowPerm;

        public DepartmentService(IQueryTask queryTask)
        {
            _queryTask = queryTask;
            _highPerm = new List<RoleEnum> { RoleEnum.Admin, RoleEnum.AdminWithoutMessage, RoleEnum.Executor };
            _lowPerm = new List<RoleEnum> { RoleEnum.Participant, RoleEnum.Other };
            _dictPerm = new Dictionary<List<RoleEnum>, Func<IQueryable<Task>>>();
        }

        #region IDepartmentService Members

        public virtual IQueryable<Task> GetTasksByDepartment(Account account, Department department)
        {
            _dictPerm.Add(_highPerm, () => _queryTask.GetTasksByDepartment(department));
            _dictPerm.Add(_lowPerm, () => _queryTask.GetTasksByDepartmentForOtherRole(account, department));
            return TasksFromDictionary(account, department);
        }

        public virtual IEnumerable<Task> GetArchiveTasksByAccount(Account account, Department department, int count)
        {
            _dictPerm.Add(_highPerm, () => _queryTask.GetArchiveTasksInOwnDepartment(account, department).Take(count));
            _dictPerm.Add(_lowPerm, () => _queryTask.GetArchiveTasksByDepartmentForOtherRole(account, department).Take(count));
            return TasksFromDictionary(account, department);
        }

        public virtual IEnumerable<Task> GetAllArchiveTasksBySearchModel(Account account, SearchModel modelSearch)
        {
            return _queryTask.GetArchiveTasksBySearchCriteria(account, modelSearch).Take(modelSearch.Count);
        }

        public virtual IEnumerable<Task> GetAllNotArchiveTasksBySearchModel(Account account, SearchModel modelSearch)
        {
            return _queryTask.GetNotArchiveTasksBySearchCriteria(account, modelSearch).Take(modelSearch.Count);
        }

        public IEnumerable<Task> GetTasksWithRatingsByDepartment(Account account, Department department, DateTime start, DateTime end)
        {
            _dictPerm.Add(new List<RoleEnum> { RoleEnum.Admin, RoleEnum.AdminWithoutMessage },
                () => _queryTask.GetTasksWithRatingsInCurrentDepartment(department, start, end));
            return TasksFromDictionary(account, department);
        }

        #endregion

        private IQueryable<Task> TasksFromDictionary(Account account, Department department)
        {
            var role = new RoleInDepartment(department, account).GetRole();
            foreach (var key in _dictPerm.Select(item => item.Key).Where(key => key.Contains(role)))
            {
                return _dictPerm[key].Invoke();
            }
            return Enumerable.Empty<Task>().AsQueryable();
        }
    }
}